#Base lines for abilities, buffs, debuffs, and dots.
import random

class Ability:
	def __init__(self,player):
		self.Cooldown = 0
		self.Player = player
	def calculateDamage(self,otherPlayer):
		raise NotImplementedError()
	def addStun(self,otherPlayer):
		return
	def use(self,otherPlayer):
		self.setCooldown()
		self.addStun(otherPlayer)
		return self.calculateDamage(otherPlayer)
	def setCooldown(self):
		raise NotImplementedError()
	def decrementCD(self):
		if(self.Cooldown>0):
			self.Cooldown -= 1
	def isOnCooldown(self):
		if(self.Cooldown > 0):
			return True
		return False
	def isAOE(self):
		return False

		
class MeleeAbility(Ability):
	def __init__(self,player):
		Ability.__init__(self,player)
	def calculateDamage(self,otherPlayer):
		return self.meleeAbilityDamage(otherPlayer)
	def setCooldown(self):
		self.Cooldown = 0	
	def meleeAbilityDamage(self,targetPlayer):
		if 5 >= random.randint(1,100) and targetPlayer.isStunned() == False:
			print(self.Name," misses!\n")
			return 0
		if targetPlayer.Avd >= random.uniform(1,100.00) and targetPlayer.isStunned() == False:
			print(targetPlayer.Name," avoids the attack!\n")
			return 0
		else:
			if self.Mcrit >= random.uniform(1,100.00): #If they player lands a critical hit for 200% damage
				self.Dmg *= 2
				print(self.Name, " lands a critical hit for double damage!")	
			if targetPlayer.Blk >= random.uniform(1,100.00) and targetPlayer.isStunned() == False: #If they player blocks, the damage is reduced by 40%
				self.Dmg = round((self.Dmg * 0.6)) #Damage is reduced by 40% if blocked
			print(targetPlayer.Name, " blocks the attack, reducing the damage taken!")		
			if self.Dmg < 0:
				self.Dmg = 0
				self.updateHealthAndOutputChanges(self.Dmg,targetPlayer)

				
class SpellAbility(Ability):
	def __init__(self,player):
		Ability.__init__(self,player)
	def calculateDamage(self,otherPlayer):
		return self.spellAbilityDamage(otherPlayer)
	def setCooldown(self):
		self.Cooldown = 0
	def spellAbilityDamage(self,targetPlayer):
		if 5 >= random.randint(1,100):
			print(self.Name," misses!\n")
			return 0
		else:
			if self.Scrit >= random.uniform(1,100.00):
				self.Dmg *= 1.5		#Spell Damage that crits is increased ty 150%
				print(self.Name, " lands a critical spell hit for increased damage!")
			if targetPlayer.Sresist >= random.uniform(1,100.00):
				self.Dmg = round((self.Dmg - (self.Dmg * (targetPlayer.Sresist * 0.01)))) 
				print(targetPlayer.Name, " resists the spell, reducing the damage taken!")
			if self.Dmg < 0:
				self.Dmg = 0
				self.updateHealthAndOutputChanges(self.Dmg,targetPlayer)

								
class Recast(SpellAbility):
	def __init__(self,player):
		Debuff.__init__(self,player)
	def calculateDamage(self,otherPlayer):
		while self.ReCastCounter == 1:
			if self.ReCast >= random.randint(1,100):
				self.Dmg = (self.Dmg + (self.Dmg * 0.3))
				self.ReCastCounter += 1
				print(self.Name,"'s spell had a multi-cast proc!\n")
			self.ReCastCounter -= 1
		return self.Dmg
						
#Debuffs
class Buff(Ability):
	def __init__(self,player):
		Ability.__init__(self,player)
		self.timeRemaining = self.setTime()
	def effect(self,otherPlayer):
		return
	def calculateDamage(self,otherPlayer):
		return 0
	def upfrontDamage(self,otherPlayer):
		raise NotImplementedError()
	def statChange(self,otherPlayer):
		raise NotImplementedError()
	def removeStatChange(self,otherPlayer):
		raise NotImplementedError()
	def decrementTime(self):
		self.timeRemaining -= 1
	def setTime(self):
		raise NotImplementedError()
	def __eq__(self,other):
		if(self.Name == other.Name):
			return True
		return False
	def use(self,otherPlayer):
		otherPlayer.addBuff(self)
		self.addStun(otherPlayer)
		return self.upfrontDamage(otherPlayer)

class Debuff(Buff):
	def __init__(self,player):
		Buff.__init__(self,player)
	def __eq__(self,other):
		if(self.Name == other.Name and self.Player.Name == other.Player.Name):
			return True
		return False
	def use(self,otherPlayer):
		otherPlayer.addDebuff(self)
		self.addStun(otherPlayer)
		return self.upfrontDamage(otherPlayer)

#DoTs class file
class DoT(Debuff):
	def __init__(self,player):
		Debuff.__init__(self,player)
	def effect(self,otherPlayer):
		self.tick(otherPlayer)
	def tick(self,otherPlayer):
		otherPlayer.HP -= self.calculateDamage(otherPlayer)
		print(otherPlayer.Name + " takes " +repr(self.Dmg) + " from "+self.Player.Name+"'s "+self.Name+".")
	def isDone(self):
		if(self.timeRemaining==0):
			return True
		return False
	def calculateDamage(self,otherPlayer):
		raise NotImplementedError()
	def decrementTime(self):
		self.timeRemaining -= 1
	def upfrontDamage(self,otherPlayer):
		raise NotImplementedError()
			
			
	



























		